package com.zhou.message.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zhou.framework.util.SettingUtil;
import com.zhou.util.FileUtil;
import com.zhou.util.Md5Util;
import com.zhou.util.PictureUtil;
import com.zhou.message.common.AttachSourceEnum;
import com.zhou.message.dao.Attachment;
import com.zhou.message.dto.AttachmentQueryDto;
import com.zhou.message.mapper.AttachmentMapper;
import com.zhou.message.dto.AttachmentDto;
import com.zhou.message.service.AttachmentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhou.org.common.EnumConstant;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.InputStream;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lang.zhou
 * @since 2023-03-01
 */
@Service
public class AttachmentServiceImpl extends ServiceImpl<AttachmentMapper, Attachment> implements AttachmentService {

    @Override
    public int saveHead(Integer userId, byte[] data,String filePath) throws Exception{
        int attachId = 0;
        //对头像进行压缩
        boolean ifZip = SettingUtil.getBoolean("uploader","userHeaderZip",true);
        int xy = SettingUtil.getInteger("uploader","userHeaderZipLine",80);

        if(ifZip && data.length > xy){
            data = PictureUtil.compressPicForScale(data,xy);
        }
        String fileName = FilenameUtils.getName(filePath);

        Attachment attach = new Attachment();
        attach.setIsPub(1);
        attach.setFileName(fileName);
        attach.setSource(AttachSourceEnum.HEAD.getEnumValue());
        attach.setSize((long) data.length);
        attach.setPrefix(FileUtil.getPrefix(fileName).toUpperCase());
        attach.setDescription("用户头像");

        attach.setType(EnumConstant.ATTACH_TYPE_HEADER);
        attach.setUserId(userId);
        attach.setFile(data);
        boolean b = SettingUtil.getBoolean("uploader", "md5Check", false);
        String md5 = Md5Util.hex(data);
        attach.setMd5(md5);
        if(b){
            Map<String,Object> par = new HashMap<>(3);
            par.put("md5",md5);
            par.put("type",attach.getType());
            par.put("userId",userId);
            Attachment n = this.getAttachByMd5(par);
            if(n != null){
                this.updateAttachDate(n.getId(),new Date());
                attachId = n.getId();
            }else{
                this.addAttach(attach);
                attachId = attach.getId();
            }
        }else{
            this.addAttach(attach);
            attachId = attach.getId();
        }
        return attachId;
    }

    @Override
    public int getAttachCountByMd5(String md5) {
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.eq(Attachment::getMd5,md5);
        return count(w);
    }

    @Override
    public Attachment getAttachByMd5(String md5) {
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.eq(Attachment::getMd5,md5);
        return baseMapper.selectOne(w);
    }

    @Override
    public Attachment getAttachByMd5(Map<String, Object> map) {
        String md5 = MapUtils.getString(map,"md5","");
        int type = MapUtils.getIntValue(map,"type",-1);
        int userId = MapUtils.getIntValue(map,"userId",-1);
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.eq(Attachment::getMd5,md5);
        if(type > -1){
            w.eq(Attachment::getType,type);
        }
        if(userId > -1){
            w.eq(Attachment::getUserId,userId);
        }
        w.orderByDesc(Attachment::getUpdateDt);
        return baseMapper.selectOne(w);
    }

    @Override
    public void addAttach(Attachment attach) {
        attach.setCreateDt(new Date());
        attach.setUpdateDt(new Date());
        save(attach);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addAttachs(List<Attachment> attachs) {
        for (Attachment attach : attachs) {
            addAttach(attach);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addAttachs(int sourceId, String sourceName, List<Attachment> attachs) {
        for (Attachment attach : attachs) {
            attach.setSourceId(sourceId);
            attach.setSource(sourceName);
            addAttach(attach);
        }
        return 0;
    }

    @Override
    public int updateAttach(Attachment attach) {
        attach.setUpdateDt(new Date());
        return baseMapper.updateById(attach);
    }

    @Override
    public void updateAttachDate(int attach, Date d) {
        LambdaUpdateWrapper<Attachment> w = new LambdaUpdateWrapper<>();
        w.set(Attachment::getUpdateDt,d);
        w.eq(Attachment::getId,attach);
        update(w);
    }

    @Override
    public int getUserHeaderIdBySeq(Map<String, Object> map) {
        return baseMapper.getUserHeaderIdBySeq(map);
    }

    @Override
    public List<Attachment> findAttachmentList(String sourceName, Integer sourceId) {
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.eq(Attachment::getSource,sourceName);
        w.eq(Attachment::getSourceId,sourceId);
        return list(w);
    }

    @Override
    public List<Attachment> findAttachmentInfoList(String sourceName, Integer sourceId) {
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.select(Attachment::getId,Attachment::getCreateDt,Attachment::getDescription,Attachment::getSource,Attachment::getSourceId,
                Attachment::getFileName,Attachment::getIsPub,Attachment::getMd5,Attachment::getPrefix,Attachment::getSize,
                Attachment::getType,Attachment::getUserId);
        w.eq(Attachment::getSource,sourceName);
        w.eq(Attachment::getSourceId,sourceId);
        return list(w);
    }

    @Override
    public List<Attachment> getAttachs(List<Integer> idList) {
        return baseMapper.selectBatchIds(idList);
    }

    @Override
    public List<Attachment> getUserAttach(Integer userId, Integer type) {
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.eq(Attachment::getUserId,userId);
        if(type != null){
            w.eq(Attachment::getType,type);
        }
        return list(w);
    }

    @Override
    public Integer getUserAttachCount(Integer userId, Integer type) {
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.eq(Attachment::getUserId,userId);
        if(type != null){
            w.eq(Attachment::getType,type);
        }
        return count(w);
    }

    @Override
    public Attachment getAttachById(Integer id) {
        if(id != null && id > 0){
            return getById(id);
        }
        return null;
    }

    @Override
    public void deleteAttach(List<Integer> idList) {
        removeByIds(idList);
    }

    @Override
    public void deleteAttachByUserId(int userId) {
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.eq(Attachment::getUserId,userId);
        remove(w);
    }

    @Override
    public List<AttachmentDto> getAttachList(AttachmentQueryDto dto) {
        return baseMapper.getAttachList(dto);
    }

    @Override
    public AttachmentDto getAttachDto(Integer id) {
        return baseMapper.getAttachDto(id);
    }

    @Override
    public Attachment getVersionAttach(String version) {
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.like(Attachment::getFileName,"version"+version+"%");
        return baseMapper.selectOne(w);
    }

    @Override
    public InputStream getAttachStream(Integer id) {
        LambdaQueryWrapper<Attachment> w = new LambdaQueryWrapper<>();
        w.eq(Attachment::getId,id);
        w.select(Attachment::getFile);
        Attachment one = baseMapper.selectOne(w);
        return one == null ? null : one.getFile();
    }

}
